﻿using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core.Framework.Util
{
    public static partial class Extensions
    {

        /// <summary>
        /// 转成json字串
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static string TryToJson<T>(this T obj) where T : class
        {
            if (obj == null)
                return string.Empty;
            return obj.TryToJson(out string errmsg);
        }

        /// <summary>
        /// 转成json字串
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static string TryToJson<T>(this T obj, out string errmsg) where T : class
        {
            return obj.TryToJson("yyyy-MM-dd HH:mm:ss", out errmsg);
        }

        /// <summary>
        /// 转成json字串
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="datetimeformats">时间格式化</param>
        /// <returns></returns>
        public static string TryToJson<T>(this T obj, string datetimeformats, out string errmsg) where T : class
        {
            
            try
            {
                errmsg = string.Empty;
                var timeConverter = new IsoDateTimeConverter { DateTimeFormat = datetimeformats };
                return JsonConvert.SerializeObject(obj, timeConverter);
            }
            catch (Exception e)
            {
                errmsg = e.Message;
                return string.Empty;
            }
        }

        /// <summary>
        /// 字串反序列化成指定对象实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static T TryToEntity<T>(this string Json)
        {
            return Json.TryToEntity<T>(out string errmsg);
        }

        /// <summary>
        /// 字串反序列化成指定对象实体
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static T TryToEntity<T>(this string Json, out string errmsg)
        {
            try
            {
                errmsg = string.Empty;
                return Json == null ? default(T) : JsonConvert.DeserializeObject<T>(Json);
            }
            catch (Exception e)
            {
                errmsg = e.Message;
                return default(T);
            }
        }

        /// <summary>
        /// 字串反序列化成指定对象实体(列表)
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static List<T> TryToList<T>(this string Json)
        {
            return Json.TryToList<T>(out string errmsg);
        }

        /// <summary>
        /// 字串反序列化成指定对象实体(列表)
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static List<T> TryToList<T>(this string Json, out string errmsg)
        {
            try
            {
                errmsg = string.Empty;
                return Json == null ? null : JsonConvert.DeserializeObject<List<T>>(Json);
            }
            catch (Exception e)
            {
                errmsg = e.Message;
                return null;
            }
            
        }

        /// <summary>
        /// 字串反序列化成linq对象
        /// </summary>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static JObject TryToJObject(this string Json)
        {
            return Json.TryToJObject(out string errmsg);
        }

        /// <summary>
        /// 字串反序列化成linq对象
        /// </summary>
        /// <param name="Json">字串</param>
        /// <returns></returns>
        public static JObject TryToJObject(this string Json, out string errmsg)
        {
            try
            {
                errmsg = string.Empty;
                return Json == null ? null : JObject.Parse(Json.Replace("&nbsp;", ""));
            }
            catch (Exception e)
            {
                errmsg = e.Message;
                return null;
            }
        }

        /// <summary>
        /// 合并两个JSON字符串
        /// 传入参数会覆盖原JSON内容
        /// </summary>
        /// <param name="Json">原始JSON</param>
        /// <param name="joinJson">连接对象</param>
        /// <returns></returns>
        public static JObject TryCombineJObject(this string Json, string joinJson)
        {
            var jObject = Json.TryToJObject();
            var join = joinJson.TryToJObject();

            if (jObject == null)
                return join;

            if (join != null)
                foreach (var item in join)
                    jObject[item.Key] = item.Value;

            return jObject;
        }

        /// <summary>
        /// 合并两个模型
        /// 传入参数优先覆盖 源
        /// </summary>
        /// <param name="t1"></param>
        /// <param name="t2">覆盖对象</param>
        /// <returns></returns>
        public static T Combine<T>(this T t1, T t2, params string[] ignore)
            where T:class
        {
            if (t1 == null)
                return t2;

            if (t2 == null)
                return t1;

            Type t = typeof(T);

            foreach (var item in t.GetProperties())
            {

                if (ignore.Contains(item.Name))
                    continue;

                var val = item.GetValue(t2);
                if (val == null)
                    continue;

                item.SetValue(t1, val);
            }

            foreach (var item in t.GetFields())
            {
                if (ignore.Contains(item.Name))
                    continue;

                var val = item.GetValue(t2);
                if (val == null)
                    continue;
                item.SetValue(t1, val);
            }

            return t1;
        }
    }
}
